home *** CD-ROM | disk | FTP | other *** search
- #include <string.h>
- #include "compress.cls"
- #include "type.h"
-
- int cpofstream::compress(uchar *inbuff, uint inbuff_len, uchar *outbuff, uchar *hash_tbl[], uint hash_len)
- {
- uchar *in_idx=inbuff;
- uchar *inbuff_end=inbuff+inbuff_len;
- uchar *anchor;
- uchar *pat_idx;
- uint cnt;
- uint gap;
- uint c;
- uint hash;
- uint *ctrl_idx=(uint*)outbuff;
- uint ctrl_bits;
- uint ctrl_cnt=0;
-
- uchar *out_idx=outbuff+sizeof(uint);
- uchar *outbuff_end=outbuff+(inbuff_len-48);
-
- if (inbuff_len <= 18)
- {
- memcpy(outbuff,inbuff,inbuff_len);
- return 0-inbuff_len;
- }
-
- hash_len--;
-
- while (in_idx < inbuff_end)
- {
- if (ctrl_cnt++==16)
- {
- *ctrl_idx=ctrl_bits;
- ctrl_cnt=1;
- ctrl_idx=(uint*)out_idx;
- out_idx+=2;
-
- if (out_idx>outbuff_end)
- {
- memcpy(outbuff,inbuff,inbuff_len);
- return 0-inbuff_len;
- }
- }
- anchor=in_idx;
- c=*in_idx++;
-
- while (in_idx < inbuff_end && *in_idx==c && (in_idx-anchor)<4114)
- in_idx++;
-
- if ((cnt=in_idx-anchor) > 2)
- {
- if (cnt<=18)
- {
- *out_idx++=cnt-3;
- *out_idx++=c;
- }
- else
- {
- cnt-=19;
- *out_idx++=16+(cnt & 0x0F);
- *out_idx++=cnt>>4;
- *out_idx++=c;
- }
- ctrl_bits=(ctrl_bits<<1) | 1;
- continue;
- }
-
- in_idx=anchor;
- if ((inbuff_end - in_idx) > 2)
- {
- hash=((((in_idx[0] & 15) << 8) | in_idx[1]) ^ ((in_idx[0]>>4) | (in_idx[2]<<4))) & hash_len;
- pat_idx=hash_tbl[hash];
- hash_tbl[hash]=in_idx;
-
- if ((gap=in_idx-pat_idx) <= 4098)
- {
- while (in_idx < inbuff_end && pat_idx < anchor && *pat_idx==*in_idx && (in_idx-anchor) < 271)
- {
- in_idx++;
- pat_idx++;
- }
- if ((cnt=in_idx-anchor) > 2)
- {
- gap-=3;
- if (cnt<=15)
- {
- *out_idx++=(cnt<<4) + (gap & 0x0F);
- *out_idx++=gap >> 4;
- }
- else
- {
- *out_idx++=32 + (gap & 0x0F);
- *out_idx++=gap >> 4;
- *out_idx++=cnt-16;
- }
- ctrl_bits=(ctrl_bits<<1) | 1;
- continue;
- }
- }
- }
- *out_idx++=c;
- in_idx=++anchor;
- ctrl_bits<<=1;
- }
- ctrl_bits<<=(16-ctrl_cnt);
- *ctrl_idx=ctrl_bits;
-
- return out_idx-outbuff;
- }
-
-